-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add best practices for building Ruby JSON APIs #365
Conversation
* Recommend that readers follow Heroku's HTTP API Design Guide when developing JSON APIs * Prefer `oj` for parsing JSON and RSpec request specs for integration testing, per iOS on Rails * References: https://github.com/thoughtbot/ios-on-rails/blob/master/book/rails/introduction.md#parsing-incoming-json-requests https://github.com/thoughtbot/ios-on-rails/blob/master/book/rails/creating_a_get_request.md#it-all-starts-with-a-request-spec
Do you think it's time we choose a side for JSON API or not? |
@drapergeek I haven't used JSON API yet so I have no opinion! Might make sense for adding JSON API to be its own PR. |
I wasn't actually recommending we back it 😄 I'll open a PR once you start this and see what people have to say. |
I don't think it make sense to be explicitly for or against JSON API since it seems situational. For example it would be great for writing the back-end of an Ember-app, but not so much for other cases like iOS/Android, or other frameworks. edit: If I had to choose though, I'd choose against. |
Why is it not a good choice for those frameworks? The general purpose and challenges involved in transmitting data via JSON seem similar for Ember and mobile apps. |
I don't have much experience from the iOS/Android side but was largely echoing what our iOS team has said in the past. As for other frameworks it doesn't seem worth the effort to parse JSON API yourself to build your models/objects when the "AMS Style" API's are a lot easier to work with. |
Do we want to cover JSON schema in this PR? |
This opinion was largely because of using a purely functional language to parse "side loaded" data. I think another PR this makes sense. |
https://github.com/thoughtbot/aeson-api/blob/master/test/Aeson/API/ParserSpec.hs
Yeah, agreed. |
@teoljungberg -- the HTTP API Design Guide recommends providing machine-readable JSON Schema schemata. Do you think additional guidelines pertaining to JSON Schema are needed here? If so, what do you have in mind? |
@malandrina If that recommendation is documented, I'm happy. |
@teoljungberg 👍 sounds good. |
I think these are all fine things. The recommendation to use oj makes sense, although it does mean that there would thereafter be a hard dependency on oj. What do you think about this? |
I have slight misgivings about recommending a specific, non-thoughtbot gem for parsing JSON because it means we'll have to revisit the recommendation every so often and confirm that there isn't a better tool for the job. That said, there is precedent: We recommend TravisCI, SendGrid and a couple other non-thoughtbot tools/services in other sections of this file. What do you think about changing the wording to be less specific? I'm thinking "Use a fast JSON parser, e.g. |
I agree about recommending a specific JSON parser. Could this be better as a blog post? It feels like several of these recommendations could change over time, and a blog post would provide more opportunity to explain why we think they're a good idea right now. For example, you could discuss what we like about the Heroku guide or show before/after benchmarks for oj. |
I think a blog post on this topic would be fantastic. However, I think it would also be nice to document our recommendations as they evolve. I view this addition to the guides as a starting point and forum for a long, ongoing conversation about how we should approach designing and building JSON APIs. Would a Trello board or another thoughtbot repository be a better place to document these decisions and conversations? |
Yeah, I think that's reasonable. I'm having a hard time thinking of things we could document that wouldn't depend on what the API was being used (authentication, versioning) for and wouldn't change quickly (oj).
I think it makes sense to create Research cards for specific ideas we're trying out, but this seems like the best place to document our findings. |
|
||
[HTTP API Design Guide]: https://github.com/interagent/http-api-design | ||
[oj]: https://github.com/ohler55/oj | ||
[request specs]: https://www.relishapp.com/rspec/rspec-rails/docs/request-specs/request-spec |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we're using an in-app JavaScript client as the primary consumer of the API, have we generally done this? Many of the applications I've seen rely on Capybara feature specs to make sure the controllers/requests are working.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the JSON Api is being consumed by something else "in process" then I agree. If your ultimate deliverable is the JSON API, then the request specs are the edge.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jferris, @derekprior -- great point. I agree. I modified this bullet point accordingly in 3e2c9db.
After reviewing our conversation here I feel confident that the concerns that have come up so far are addressed as of 3e2c9db. Does anyone want to share any additional thoughts or concerns before I merge this? |
This generally looks good to me. I have to look through Heroku's API design guide some more. I wonder if we should specifically mention the parts from that guide that we endorse, since Heroku's ideas will evolve over time and won't necessarily mirror our own at all times. |
I saw this post in Ruby Weekly and thought it might be relevant to this convo: http://multithreaded.stitchfix.com/blog/2015/11/04/simple-rails-apis-with-stitches/ |
@boddhisattva thanks for the feedback. I think you’re right that the phrase “in-app JavaScript client” is a bit cryptic. I’m hesitant to include a specific example because I’m trying to keep this section as concise as possible, but I did attempt to make the wording more descriptive in c7eb113. @jferris good point — I think it’s a good idea to specify the sections of the Heroku API design guide we endorse. To me it looks like everything in the Responses, Requests and Artifacts sections is consistent with what we do (or aspire to do) now; I think Rails automatically does a lot of stuff advised in the Foundations section, but there are a couple things I’m not sure about, e.g. dividing large responses across requests with ranges. @jessieay, thanks for the link! It’s cool to see how agreeing on a set of conventions gave StitchFix a foundation for building API-related tooling.
|
lurking ActiveModelSerializers collaborator here... we're definitely pro-JSON API and it's a goal for Rails. There's plenty of client and server libraries for JSON API. I personally want to get schema validation into ActiveModelSerializers. I think the 'holy grail' of API development would be something like Document Driven Contracts
I also like the https://github.com/cerebris/jsonapi-resources/ gem a lot. |
@bf4 If we as the Ruby community could come up with a tool that does all of those things in one bundle, and does it really well, that would be AMAZING. One tool I've been wanting to try out that I saw a while back that might make it easier to do these kinds of things (specifically generating good documentation) was RAML. |
@bf4 thanks for sharing your thoughts. I agree with @mcmire — if we could bundle all of that functionality together it would be incredible! On a related note, but at the risk of derailing the broader conversation here about best practices, I have a post for the thoughtbot blog in review that covers the different JSON Schema-based tooling available in Ruby (the Heroku gems, This experience makes me think that the main obstacle to developing an integrated suite of JSON Schema-based tools for Ruby web apps is ensuring that they all have compatible assumptions about the organization and structure of the schemata. @mcmire, RAML looks cool! Not to mention WAY more user-friendly than JSON Schema. We should give it a try when the opportunity arises. |
Oh, definitely. While it's nice that we have separate tools that do separate things, and you can in theory use them on their own, they have to share that assumption. Coming back to this PR, is there anything we need to add to merge it? |
@mcmire, in #365 (comment) @jferris mentioned that he'd like to take a closer look at Heroku's API design guide. We may want to recommend specific sections of the guide rather than the whole thing. Otherwise there are no outstanding discussion items. |
I haven't followed all of the details in this conversation, but feel that two public efforts to solving this problem are probably worth noting (since I haven't seen reference to them yet):
I hope these references help and provide some guidance. |
That's a good point. I think that providing documentation for an API you're building is really important, and you should do it. Of course, there are different ways to do it. I haven't tried any of the API generation tools out there except for prmd, although I have high standards when it comes to documentation:
Notable services that have quality documentation: So those are my thoughts on generating documentation. I personally haven't used any of the API generation tools except for prmd, but any tool that we choose, I feel, needs to follow the guidelines above. |
@malandrina Thanks for your detailed explanation. It really helped me to better understand where you are coming from based on the guidelines that you've written thus far wrt this PR. When I just read the first sentence of the third guideline, it basically says |
@toobulkeh etc, fwiw, a nice tooling list someone's made I also really like the balanced-api approach to documentation testing
|
@toobulkeh, @bf4 -- thanks for linking to all those resources! I know some folks at thoughtbot have used at least some of those standards and tools; my hope is that this section of the guides will help us formalize the adoption of the tools and workflows we find work best for us after we've taken them through our internal review process (a process we discuss in this episode of The Bike Shed podcast, if anyone is curious to learn more). @boddhisattva, I see where you're coming from, but I think all of the best practices guidelines here are accompanied by an implicit directive to use your discretion, and I don't think it's necessary to make that directive explicit in this case. @mcmire, just wanted to say I agree with all the points you made: You laid out an excellent framework for evaluating API documentation tools. Pinging @jferris: Have you had a chance to look at Heroku's API design guide? |
Looking through Heroku's API design guide, there aren't any points I really disagree with. Their design guide is fairly large, though, and it seems unlikely that we have group buy-in on every idea in there. There are several that I'm not sure I've seen at thoughtbot, such as 1.5 (setting We may want to recommend reading the Heroku API deisgn guide when designing a new API. If we've found some that are useful and near-universal from our own experience, we may want to reference them or replicate them in our own guide. |
@mcmire It looks like you have described API Blueprint where you get tools for rendering documentation for testing etc ... it is a shameless plug as I am actually working on those tools but I think they are worth checking as the philosophy and ideas behind it are very similar to what are your requirements. |
@w-vi Nice, thanks for sharing your tools! |
@jferris sorry it's taken me a few weeks to address your feedback. Thanks for taking a look at the Heroku guide. The guide is indeed fairly large, and I agree that advising readers to adhere to all of its recommendations is too prescriptive at this point. In my recent commit I changed the wording to:
I think this wording is better because it points readers in the right direction but doesn't ask them to commit to a bunch of conventions and approaches we haven't evaluated yet. |
|
||
* Review the recommended practices outlined in Heroku's [HTTP API Design Guide] | ||
before designing a new API. | ||
* Use a fast JSON parser, e.g. [`oj`][oj] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oj out of the box doesn't do exactly what you might expect:
irb(main):004:0> puts Oj.dump(foo: 'baz')
{":foo":"baz"}
I'd add a note here that for Ruby hashes w/ symbols you need to enable compat
mode.
irb(main):005:0> Oj.default_options = {:mode => :compat }
=> {:mode=>:compat}
irb(main):006:0> puts Oj.dump(foo: 'baz')
{"foo":"baz"}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like for Rails 4.1~ there's a new gem that can be included:
https://github.com/ohler55/oj#compatibility
gem 'oj'
gem 'oj_mimic_json'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@harlow good to know, thank you! I went ahead and merged this as-is but will see about expanding the recommendation to use oj
to include some caveats about its usage in a separate PR.
All of the current proposed changes make sense to me. |
Did that get published? I haven't found it. |
@bf4 nope, I kind of lost steam on that blog post because of the compatibility issues I encountered. It'd probably be worthwhile to revisit it though. I'll take a look this Friday. |
@malandrina still no great resources on this for non json schema experts:( |
developing JSON APIs
oj
for parsing JSON and RSpec request specs for integrationtesting, per iOS on Rails
https://github.com/thoughtbot/ios-on-rails/blob/master/book/rails/introduction.md#parsing-incoming-json-requests
https://github.com/thoughtbot/ios-on-rails/blob/master/book/rails/creating_a_get_request.md#it-all-starts-with-a-request-spec